﻿
Imports osi.root.delegates
Imports osi.root.connector
Imports osi.root.formation
Imports osi.root.procedure
Imports osi.root.utils
Imports osi.service.argument
Imports osi.service.configuration
Imports osi.service.selector

Partial Public Class device_constructor(Of T)
    Private Shared ReadOnly lt As lazier(Of T, String, var)
    Private Shared l As lazier(Of T, var)

    Shared Sub New()
        lt = New lazier(Of T, String, var)()
    End Sub

    Private Sub New()
    End Sub

    Public Shared Function register(ByVal allocator As allocator(Of T, var)) As Boolean
        If allocator Is Nothing OrElse Not l Is Nothing Then
            Return False
        Else
            l = New lazier(Of T, var)(allocator)
            Return True
        End If
    End Function

    Public Shared Function [erase]() As Boolean
        If l Is Nothing Then
            Return False
        Else
            l = Nothing
            Return True
        End If
    End Function

    Public Shared Function register(ByVal type As String,
                                    ByVal allocator As allocator(Of T, var)) As Boolean
        If l Is Nothing Then
            Return lt.register(type, allocator)
        Else
            Return False
        End If
    End Function

    Public Shared Function [erase](ByVal type As String) As Boolean
        Return lt.erase(type)
    End Function

    Public Shared Sub clear_create_singleton_device_pool_binder()
        binder(Of _do_val_ref(Of T, singleton_device_pool(Of T), Boolean), device_constructor(Of T)).set_global(Nothing)
    End Sub

    Public Shared Sub set_create_singleton_device_pool_binder(ByVal x As _do_val_ref(Of T, 
                                                                                        singleton_device_pool(Of T),
                                                                                        Boolean))
        binder(Of _do_val_ref(Of T, singleton_device_pool(Of T), Boolean), device_constructor(Of T)).set_global(x)
    End Sub

    Public Shared Sub set_create_singleton_device_pool_binder(ByVal x As Func(Of T, singleton_device_pool(Of T)))
        If x Is Nothing Then
            clear_create_singleton_device_pool_binder()
        Else
            set_create_singleton_device_pool_binder(Function(c As T, ByRef o As singleton_device_pool(Of T)) As Boolean
                                                        o = x(c)
                                                        Return True
                                                    End Function)
        End If
    End Sub

    Public Shared Sub clear()
        [erase]()
        lt.clear()
        clear_create_singleton_device_pool_binder()
    End Sub

    Private Shared Function register_device(ByVal name As String,
                                            ByVal d As T,
                                            ByVal create_singleton_device_pool As  _
                                                binder(Of _do_val_ref(Of T, 
                                                                         singleton_device_pool(Of T),
                                                                         Boolean), 
                                                          device_constructor(Of T))) As Boolean
        assert(Not d Is Nothing)
        If String.IsNullOrEmpty(name) Then
            'no name means we do not need to register it
            Return True
        ElseIf d.is(GetType(idevice_pool)) Then
            Return device_manager.register(name, d)
        ElseIf create_singleton_device_pool.has_value() Then
            Dim p As singleton_device_pool(Of T) = Nothing
            Return (+create_singleton_device_pool)(d, p) AndAlso
                   device_manager.register(name, p)
        Else
            Return True
        End If
    End Function

    Friend Shared Function register_device(ByVal v As var,
                                           ByVal d As T,
                                           ByVal create_singleton_device_pool As  _
                                               binder(Of _do_val_ref(Of T, 
                                                                        singleton_device_pool(Of T),
                                                                        Boolean), 
                                                         device_constructor(Of T))) As Boolean
        assert(Not v Is Nothing)
        Return register_device(v("name"), d, create_singleton_device_pool)
    End Function

    Public Shared Function resolve_only(ByVal type As String,
                                        ByVal v As var,
                                        ByVal o As pointer(Of T)) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  o.renew()
                                  If l Is Nothing Then
                                      If String.IsNullOrEmpty(type) Then
                                          Return False
                                      End If
                                      ec = lt(type, v, o)
                                  Else
                                      ec = l(v, o)
                                  End If
                                  assert(Not ec Is Nothing)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  If ec.end_result() Then
                                      ec = device_wrapper(Of T).wrap(type, v, +o, o)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  Else
                                      Return False
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Shared Function resolve_only(ByVal v As var, ByVal o As pointer(Of T)) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If v Is Nothing Then
                                      Return False
                                  Else
                                      ec = resolve_only(v("type"), v, o)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Private Shared Function resolve_register(ByVal v As var,
                                             ByVal o As pointer(Of T),
                                             ByVal r As Func(Of var, pointer(Of T), event_comb),
                                             ByVal create_singleton_device_pool As  _
                                                 binder(Of _do_val_ref(Of T, 
                                                                          singleton_device_pool(Of T),
                                                                          Boolean), 
                                                           device_constructor(Of T))) As event_comb
        assert(Not r Is Nothing)
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  o.renew()
                                  ec = r(v, o)
                                  Return waitfor(ec) AndAlso
                                         goto_next()
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         register_device(v,
                                                         +o,
                                                         create_singleton_device_pool) AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Shared Function resolve(ByVal type As String,
                                   ByVal v As var,
                                   ByVal o As pointer(Of T),
                                   Optional ByVal create_singleton_device_pool As  _
                                       binder(Of _do_val_ref(Of T, 
                                                                singleton_device_pool(Of T),
                                                                Boolean), 
                                                 device_constructor(Of T)) = Nothing) As event_comb
        Return resolve_register(v,
                                o,
                                Function(x, y) resolve_only(type, x, y),
                                create_singleton_device_pool)
    End Function

    Public Shared Function resolve(ByVal v As var,
                                   ByVal o As pointer(Of T),
                                   Optional ByVal create_singleton_device_pool As  _
                                       binder(Of _do_val_ref(Of T, 
                                                                singleton_device_pool(Of T),
                                                                Boolean), 
                                                 device_constructor(Of T)) = Nothing) As event_comb
        Return resolve_register(v,
                                o,
                                Function(x, y) resolve_only(x, y),
                                create_singleton_device_pool)
    End Function

    Public Shared Function resolve(ByVal type As String,
                                   ByVal v As section,
                                   ByVal o As pointer(Of T),
                                   Optional ByVal create_singleton_device_pool As  _
                                       binder(Of _do_val_ref(Of T, 
                                                                singleton_device_pool(Of T),
                                                                Boolean), 
                                                 device_constructor(Of T)) = Nothing) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If v Is Nothing Then
                                      Return False
                                  Else
                                      ec = resolve(type, New var(v.values()), o, create_singleton_device_pool)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function

    Public Shared Function resolve(ByVal v As section,
                                   ByVal o As pointer(Of T),
                                   Optional ByVal create_singleton_device_pool As  _
                                       binder(Of _do_val_ref(Of T, 
                                                                singleton_device_pool(Of T),
                                                                Boolean), 
                                                 device_constructor(Of T)) = Nothing) As event_comb
        Dim ec As event_comb = Nothing
        Return New event_comb(Function() As Boolean
                                  If v Is Nothing Then
                                      Return False
                                  Else
                                      ec = resolve(New var(v.values()), o, create_singleton_device_pool)
                                      Return waitfor(ec) AndAlso
                                             goto_next()
                                  End If
                              End Function,
                              Function() As Boolean
                                  Return ec.end_result() AndAlso
                                         goto_end()
                              End Function)
    End Function
End Class
